home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / util / moni / CPULoad_JS.lha / CPULoad.c < prev    next >
C/C++ Source or Header  |  1995-03-29  |  11KB  |  414 lines

  1. /*
  2.     CPULoad
  3.     (C) Thomas Radtke 1994
  4.  
  5.     main:        Process, Initialisierungen und buisy loop
  6.     druck:        Task, Graphische Ausgabe
  7.     IdleIrq:    IRQ server, Auswertung des buisy loop
  8.  
  9.     Um double-Rechnungen zu vermeiden werden ULONG's in beide Richtungen
  10.     geshiftet. Bei hohen Rechenleistungen kann dies ggf. zu Überläufen
  11.     führen. Abhilfe bringt eine Verringerung des 'aktuell'-Wertes
  12.     ('aktuell>>n') um ein geeignetes n.
  13.  
  14.     Das Abbruchsignal ist CTRL-D. Niemals CTRL-C verwenden, wenn der
  15.     Compiler dieses Signal als generellen Abbruch benutzt.
  16.  
  17.     Basiert auf Idle LED von Lindsay Meek.
  18.  
  19.     read the README !
  20.  
  21.  
  22.     Version 1.1 modifications (Mar-26-95) by Jean-Guy Speton:
  23.  
  24.         - Fixed source to compile with DICE 3.0, which mainly involved the
  25.           insertion of __geta4 for IdleCPU() and druck().
  26.         - Added prototype #include's, removed local protypes of system calls,
  27.           which made my system crash.  :-(
  28.         - Changed comments to C++ style, which I prefer, and deleted some
  29.           German comments which I didn't understand.  Apologies to Thomas.
  30.         - cast'ed system calls to get rid of compiler warnings.
  31.         - Replaced explicit priority changes with calls to SetTaskPri().
  32.         - Replaced explicit signal changes and queries with SetSignal().
  33.         - Window now opened with OpenWindowTags rather than OpenWindow().
  34.         - Changed expensive GIMMEZEROZERO window to non-GZZ window.
  35.         - Changed CTRL-D handling to CTRL-C, so you can 'break' it from a CLI.
  36.         - Added hash lines at 1/4, 1/2 and 3/4 the way down the window.
  37.           Set the colour yourself if you don't like mine by changing HASH_PEN.
  38.         - Removed sizing gadget and added zip gadget, the way I like it.
  39.           (I thought the sizing gadget made the window look ugly.)
  40.         - Added command line options LEFT, TOP, WIDTH and HEIGHT to specify
  41.           initial location and size of window.
  42.         - Added UPDATE command line option, which sets how often the graph is
  43.           updated.  ie. Update every UPDATE seconds.  Default is 1.
  44. */
  45.  
  46. const char *dummy="$VER: CPULoad 1.1";
  47.  
  48. #include <intuition/intuitionbase.h>
  49. #include <exec/nodes.h>
  50. #include <exec/tasks.h>
  51. #include <exec/interrupts.h>
  52. #include <hardware/intbits.h>
  53. #include <libraries/dos.h>
  54. #include <exec/types.h>
  55. #include <exec/memory.h>
  56. #include <stdlib.h>
  57. #include <stdio.h>
  58. #include <signal.h>
  59.  
  60. #include <clib/alib_protos.h>
  61. #include <clib/exec_protos.h>
  62. #include <clib/intuition_protos.h>
  63. #include <clib/dos_protos.h>
  64.  
  65. __geta4 void druck(void);
  66. __geta4 int IdleCPU(void);
  67.  
  68. #define HASH_PEN    0            // Pen used for hash lines.
  69.  
  70. // Template string and variables used for command line arguments.
  71.  
  72. #define TEMPLATE "L=LEFT/N,T=TOP/N,W=WIDTH/N,H=HEIGHT/N,U=UPDATE/N"
  73. LONG WIN_LEFT, WIN_TOP, WIN_WIDTH, WIN_HEIGHT, UPDATE;
  74.  
  75. BOOL must_quit = FALSE;
  76.  
  77. // Stacksize für den Grafik-Task (1000 < STACK_SIZE < 10000)
  78.  
  79. #define STACK_SIZE 4000L
  80.  
  81. struct Task *task = NULL;
  82. char *taskname = "CPULoad";
  83.  
  84. struct timerequest *tr;
  85. struct MsgPort *tport;
  86. struct Message *msg;
  87. struct Window *CustWindow;
  88. struct IntuitionBase *IntuitionBase;
  89. struct GfxBase *GfxBase;
  90.  
  91. #define rp CustWindow->RPort
  92. #define bl CustWindow->BorderLeft
  93. #define bt CustWindow->BorderTop
  94. #define br CustWindow->BorderRight
  95. #define bb CustWindow->BorderBottom
  96. #define ww CustWindow->Width
  97. #define wh CustWindow->Height
  98.  
  99. unsigned int maximum,aktuell;
  100.  
  101. struct Task *met2;
  102.  
  103. #define UTILITY_NAME "IdleCPU"
  104.  
  105. // Various counters used to detect the idle state in the vblank.
  106.  
  107. static ULONG idle_vbi_cnt_limit[3];
  108.  
  109. struct timerequest *create_timer(ULONG unit)
  110. {
  111.     LONG error;
  112.     struct MsgPort *timerport;
  113.     struct timerequest *timermsg;
  114.  
  115.     if ((timerport = (struct MsgPort *)CreatePort(0,0)) == NULL)
  116.         exit(1);
  117.     if ((timermsg = (struct timerequest *)CreateExtIO(timerport,sizeof(struct timerequest))) == NULL)
  118.         exit(1);
  119.     if ((error = OpenDevice(TIMERNAME,unit,(struct IORequest *)timermsg,0)) != 0)
  120.         exit(1);
  121.     return(timermsg);
  122. }
  123.  
  124. __geta4 int IdleCPU() {
  125.     idle_vbi_cnt_limit[0] = 1;
  126.     aktuell = idle_vbi_cnt_limit[1];
  127.     idle_vbi_cnt_limit[1] = 0;
  128.     return 0;
  129. }
  130.  
  131. __geta4 void druck() {
  132.     struct IntuiMessage *message;
  133.     struct timeval updateval;
  134.     LONG n;
  135.     unsigned int sum;
  136.     LONG height,width,left,right,top,bottom;
  137.     ULONG int_pix_per_load;
  138.     int whitepen,blackpen;
  139.     struct Screen *PubScreen;
  140.     short pen,minpen,maxpen;
  141.     unsigned short RGB;
  142.     int class;
  143.  
  144.     // init timer
  145.  
  146.     tr = create_timer(UNIT_MICROHZ);
  147.  
  148.     updateval.tv_secs=0;
  149.     updateval.tv_micro=100000;    /*    1/10 secs    */
  150.  
  151.     IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
  152.     GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
  153.  
  154.     PubScreen = LockPubScreen(NULL);
  155.  
  156.     WORD zoom_words[4] = {WIN_LEFT, WIN_TOP, WIN_WIDTH, PubScreen->WBorTop + PubScreen->Font->ta_YSize + 1};
  157.  
  158.     CustWindow = OpenWindowTags(NULL,
  159.                     WA_Left,    WIN_LEFT,
  160.                     WA_Top,        WIN_TOP,
  161.                     WA_Width,    WIN_WIDTH,
  162.                     WA_Height,    WIN_HEIGHT,
  163.                     WA_MinWidth,50,
  164.                     WA_MinHeight,25,
  165.                     WA_IDCMP,    CLOSEWINDOW | NEWSIZE | CHANGEWINDOW,
  166.                     WA_Flags,    ACTIVATE | SMART_REFRESH | WINDOWCLOSE | WINDOWDRAG | WINDOWDEPTH,
  167.                     WA_Title,    "CPULoad",
  168.                     WA_PubScreen,PubScreen,
  169.                     WA_Zoom,    zoom_words,
  170.                     NULL);
  171.  
  172.     UnlockPubScreen(NULL,PubScreen);
  173.     CustWindow->MinHeight = bt;
  174.  
  175.     whitepen = 1;
  176.     blackpen = 0;
  177.     maxpen = 0x000;
  178.     minpen = 0xfff;
  179.  
  180.     for (n = 0; n < (1 << PubScreen->BitMap.Depth); n++) {
  181.         RGB = GetRGB4(PubScreen->ViewPort.ColorMap,n);
  182.  
  183.         pen = (RGB & 0x00f) + ((RGB & 0x0f0) >> 4) + ((RGB & 0xf00) >> 8);
  184.  
  185.         if (pen < minpen) {
  186.             minpen = pen;
  187.             blackpen = n;
  188.         }
  189.         if (pen > maxpen) {
  190.             maxpen = pen;
  191.             whitepen = n;
  192.         }
  193.     }
  194.  
  195.     height = wh - bt - bb;
  196.     width  = ww - br - bl;
  197.     left   = bl;
  198.     right  = left + width - 1;
  199.     top    = bt;
  200.     bottom = bt + height - 1;
  201.  
  202.     SetAPen(rp,whitepen);
  203.     RectFill(rp,left,top,right,bottom);
  204.  
  205.     SetAPen(rp, HASH_PEN);
  206.     Move(rp, left, top + height/4);
  207.     Draw(rp, right, top + height/4);
  208.     Move(rp, left, top + height/2);
  209.     Draw(rp, right, top + height/2);
  210.     Move(rp, left, top + 3*height/4);
  211.     Draw(rp, right, top + 3*height/4);
  212.  
  213.     while (1) {
  214.  
  215.         if (must_quit) {
  216.             Signal(met2, SIGBREAKF_CTRL_D);
  217.             Wait(0L);
  218.         }
  219.  
  220.         sum = 0;
  221.         for (n = 0; n < 10; n++) {
  222.             sum += aktuell;
  223.  
  224.             updateval.tv_micro = 100000 * UPDATE;
  225.  
  226.             tr->tr_node.io_Command = TR_ADDREQUEST;
  227.             tr->tr_time = updateval;
  228.             DoIO((struct IORequest *)tr);
  229.         }
  230.  
  231.         sum /= 10;    // Average over 10 samples.
  232.  
  233.         if (wh > bt) {
  234.             height = wh - bt - bb;
  235.             width  = ww - br - bl;
  236.             left   = bl;
  237.             right  = left + width - 1;
  238.             top    = bt;
  239.             bottom = bt + height - 1;
  240.  
  241.             int_pix_per_load = (height<<16)/maximum;
  242.  
  243.             ScrollRaster(rp,1,0,left,top,right,bottom);
  244.  
  245.             Move(rp,right,bottom);
  246.  
  247.             SetAPen(rp,blackpen);
  248.             Draw(rp, right, top + ((sum * int_pix_per_load) >> 16));
  249.             if (rp->cp_y > top) {
  250.                 SetAPen(rp,whitepen);
  251.                 Draw(rp,right,top);
  252.             }
  253.  
  254.             // Fill in the displaced hash-line points.
  255.  
  256.             SetAPen(rp, HASH_PEN);
  257.             Move(rp, right, top + height/4);
  258.             Draw(rp, right, top + height/4);
  259.             Move(rp, right, top + height/2);
  260.             Draw(rp, right, top + height/2);
  261.             Move(rp, right, top + 3*height/4);
  262.             Draw(rp, right, top + 3*height/4);
  263.         }
  264.  
  265.         while (message = (struct IntuiMessage *)GetMsg(CustWindow->UserPort)) {
  266.             if ((class = message->Class) == CLOSEWINDOW) {
  267.                 ReplyMsg((struct Msg *)message);
  268.                 Signal(met2, SIGBREAKF_CTRL_C);
  269.                 Signal(met2, SIGBREAKF_CTRL_D);
  270.                 SetTaskPri(met2, 1L);    // So it doesn't have to wait if CPU usage is 100%.
  271.                 Wait(0L);    // Parent process will DeleteTask() us.
  272.             }
  273.             else if (class == NEWSIZE) {
  274.                 ReplyMsg((struct Msg *)message);
  275.                 if (wh > bt) {
  276.                     SetAPen(rp,whitepen);
  277.                     RectFill(rp,left,top,right,bottom);
  278.                     SetAPen(rp, HASH_PEN);
  279.                     Move(rp, left, top + height/4);
  280.                     Draw(rp, right, top + height/4);
  281.                     Move(rp, left, top + height/2);
  282.                     Draw(rp, right, top + height/2);
  283.                     Move(rp, left, top + 3*height/4);
  284.                     Draw(rp, right, top + 3*height/4);
  285.                 }
  286.             }
  287.             else if (class == CHANGEWINDOW)
  288.                 ReplyMsg((struct Msg *)message);
  289.         }
  290.     }
  291. }
  292.  
  293. // Run this as a process. It aborts when it detects a CTRL_C signal.
  294.  
  295. main()
  296. {
  297.     struct Task *met;
  298.     struct Interrupt mei;
  299.     WORD oldpri;
  300.     char *oldname;
  301.     struct RdArgs *ra;
  302.     LONG args[5] = { 0L, 0L, 0L, 0L, 0L };
  303.  
  304.     // Switch off CTRL_C handling, we'll handle it ourselves.
  305.  
  306.     signal(SIGINT,SIG_IGN);
  307.  
  308.     // Read command-line arguments.
  309.  
  310.     if (ra = ReadArgs(TEMPLATE, args, NULL)) {
  311.         WIN_LEFT   = (args[0] ? *(LONG *)args[0] : 0);
  312.         WIN_TOP    = (args[1] ? *(LONG *)args[1] : 0);
  313.         WIN_WIDTH  = (args[2] ? *(LONG *)args[2] : 130);
  314.         WIN_HEIGHT = (args[3] ? *(LONG *)args[3] : 100);
  315.         UPDATE     = (args[4] ? *(LONG *)args[4] : 1);
  316.         if (UPDATE < 1)        // A value of 0 would be unacceptable.
  317.             UPDATE = 1;
  318.         FreeArgs(ra);
  319.     }
  320.     else
  321.         exit(1);
  322.  
  323.     // Remove CPULoad if already present.
  324.  
  325.     if (met = FindTask(UTILITY_NAME)) {
  326.         Signal(met,SIGBREAKF_CTRL_C);
  327.         exit(0);
  328.     }
  329.  
  330.     // Setup for IRQ
  331.  
  332.     mei.is_Node.ln_Type = NT_INTERRUPT;
  333.     mei.is_Node.ln_Pri  = -127;
  334.     mei.is_Node.ln_Name = UTILITY_NAME;
  335.     mei.is_Data = (APTR)0;    // idle_vbi_cnt_limit;
  336.     mei.is_Code = (void *)IdleCPU;
  337.  
  338.     AddIntServer(INTB_VERTB, &mei);        // Install IRQ server.
  339.  
  340.     met=FindTask(NULL);
  341.     oldname=met->tc_Node.ln_Name;        // Save old name.
  342.     met->tc_Node.ln_Name=UTILITY_NAME;
  343.  
  344.     oldpri = SetTaskPri(met, 40);
  345.  
  346.     met2 = met;    // Pointer for druck().
  347.  
  348.     // Reset counters.
  349.  
  350.     idle_vbi_cnt_limit[0]=0;
  351.     idle_vbi_cnt_limit[1]=0;
  352.     idle_vbi_cnt_limit[2]=0;
  353.  
  354.     // Wait for next vbi, nicht ganz astrein.
  355.  
  356.     Forbid();
  357.  
  358.     while(idle_vbi_cnt_limit[0] == 0) ;
  359.  
  360.     // Count # of increments in one frame (for calibration).
  361.  
  362.     idle_vbi_cnt_limit[2] = 0;
  363.     idle_vbi_cnt_limit[0] = 0;
  364.     while (idle_vbi_cnt_limit[0] == 0)
  365.         idle_vbi_cnt_limit[2]++;
  366.  
  367.     Permit();
  368.  
  369.     // druck() braucht maximum
  370.  
  371.     maximum = idle_vbi_cnt_limit[2];
  372.  
  373. //    printf("%d\n",maximum); fflush(stdout);
  374.  
  375.     task = CreateTask(taskname,30,druck,STACK_SIZE);
  376.  
  377.     SetTaskPri(met, -127);
  378.  
  379.     // Busy loop for eating up idle CPU cycles.
  380.  
  381.     SetSignal(0L, SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D);        // Ignore queued CTRL_C and CTRL_D.
  382.  
  383.     while((met->tc_SigRecvd & SIGBREAKF_CTRL_C) == 0)     // Abort on CTRL_C
  384.         idle_vbi_cnt_limit[1]++;        // Increment idle counter
  385.  
  386.     // We cannot remove the child if it's waiting for timer IO
  387.     //  so we wait for it to send us a CTRL_D, which means it
  388.     //  is ready to be killed.
  389.  
  390.     must_quit = TRUE;        // Let the task know it must quit.
  391.     Wait(SIGBREAKF_CTRL_D);
  392.  
  393.     RemIntServer(INTB_VERTB,&mei);        // Remove IRQ server.
  394.     SetTaskPri(met, oldpri);
  395.     met->tc_Node.ln_Name=oldname;        // Change name back.
  396.  
  397.     if (tr) {
  398.         CloseDevice((struct IORequest *)tr);
  399.         DeleteExtIO((struct IORequest *)tr);
  400.     }
  401.  
  402.     if (CustWindow)
  403.         CloseWindow(CustWindow);
  404.  
  405.     DeleteTask(task);
  406.  
  407.     if (IntuitionBase)
  408.         CloseLibrary((struct Library *)IntuitionBase);
  409.     if (GfxBase)
  410.         CloseLibrary(GfxBase);
  411.  
  412.     exit(0);
  413. }
  414.